package com.appium.manager.template.core;

import com.appium.manager.config.AppiumConfig;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.MobileCapabilityType;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.TimeUnit;

import static com.appium.manager.config.AppiumConfig.*;
import static com.appium.manager.data.TestDataHandler.DEFAULT_TEST_DATA_FILE_PATH;


/**
 * 混合测试层抽象层
 * @author 大忽悠
 * @create 2022/7/7 10:17
 */
@Slf4j
public abstract class AbstractHybridTemplate implements AppiumTemplate {
    /**
     * 配置类
     */
    protected AppiumConfig appiumConfig;
    /**
     * 驱动
     */
    protected AndroidDriver<WebElement>  androidDriver;
    /**
     * 测试数据文件路径--如果不配置,就用默认appiumTestData.yml
     */
    protected String testDataFilePath=DEFAULT_TEST_DATA_FILE_PATH;
    /**
     * 配置文件默认路径
     */
    protected String appiumConfigFilePath=DEFAULT_CONFIG_FILE_PATH;
    /**
     * 是否已经初始化完毕
     */
    private boolean initFlag=false;


    /**
     * 初始化appiumClient客户端和元素定位器
     */
    @Override
    public void init() {
        if(initFlag){
            throw new UnsupportedOperationException("请勿重复初始化");
        }
        try {
            beforeInit();
            appiumConfig=new AppiumConfig(appiumConfigFilePath);
            androidDriver=initDriver();
            afterInit();
        } catch (MalformedURLException e) {
           throw new RuntimeException("appium服务器连接失败,请检查"+appiumConfig.getParam(APPIUM_SERVER_ADDRESS)+"地址是否配置正确");
        }
        initFlag=true;
    }

    /**
     * 钩子方法,子类可以重写
     */
    protected void afterInit() {}

    /**
     * 钩子方法,子类可以重写
     */
    protected void beforeInit() {}

    /**
     * 初始化驱动
     */
    private AndroidDriver<WebElement> initDriver() throws MalformedURLException {
        DesiredCapabilities desiredCapabilities=new DesiredCapabilities();
        desiredCapabilities.setCapability(DEVICE_NAME,appiumConfig.getParam(DEVICE_NAME));
        desiredCapabilities.setCapability(PLATFORM_NAME,appiumConfig.getParam(PLATFORM_NAME));
        desiredCapabilities.setCapability(APP_PACKAGE,appiumConfig.getParam(APP_PACKAGE));
        desiredCapabilities.setCapability(APP_ACTIVITY,appiumConfig.getParam(APP_ACTIVITY));
        desiredCapabilities.setCapability(AUTOMATION_NAME,appiumConfig.getParam(AUTOMATION_NAME));
        desiredCapabilities.setCapability(NO_RESET,appiumConfig.getParam(NO_RESET));
        //用于客户端在退出或者结束session之前,Appium等待客户端发送一条新命令所花费的世界(秒为单位)
        desiredCapabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT,600);

        String appPath = appiumConfig.getParam(APP);

        //判断是否需要重新安装
        if(Boolean.parseBoolean(appiumConfig.getParam(CLEAR_SYSTEM_FILES))){
            log.info("每次启动应用程序前会先卸载并重新安装");
            desiredCapabilities.setCapability(MobileCapabilityType.CLEAR_SYSTEM_FILES,appiumConfig.getParam(CLEAR_SYSTEM_FILES));
            desiredCapabilities.setCapability(MobileCapabilityType.APP,appPath);
        }

        //判断是否开启了IOS测试环境
        if(appiumConfig.openIOS()){
            desiredCapabilities.setCapability(MobileCapabilityType.UDID,appiumConfig.getParam(UDID));
            desiredCapabilities.setCapability(MobileCapabilityType.APP,appiumConfig.getParam(APP));
        }

        log.info("当前应用程序的apk路径被设置为了: {},只有在设置了clearSystemFiles属性或者开启了IOS环境的情况下,才需要去管!!!",appPath);

        log.info("设置的desiredCapabilities属性为: {}",desiredCapabilities);

        AndroidDriver<WebElement>  androidDriver = new AndroidDriver<WebElement> (new URL(appiumConfig.getParam(APPIUM_SERVER_ADDRESS)), desiredCapabilities);
        androidDriver.manage().timeouts().implicitlyWait(Long.parseLong(appiumConfig.getParam(IMPLICITLY_WAIT)), TimeUnit.SECONDS);
        this.androidDriver=androidDriver;
        this.androidDriver.context(appiumConfig.getParam(WEBVIEW_CONTEXT));
        return androidDriver;
    }

    public void setAppiumConfig(AppiumConfig appiumConfig) {
        this.appiumConfig = appiumConfig;
    }

    public void setTestDataFilePath(String testDataFilePath) {
        this.testDataFilePath = testDataFilePath;
    }

    public void setAppiumConfigFilePath(String appiumConfigFilePath) {
        this.appiumConfigFilePath = appiumConfigFilePath;
    }

    /**
     * 获取驱动---需要手动定制时,可以获取
     */
    public AndroidDriver<WebElement> getAndroidDriver(){
        return androidDriver;
    }

    /**
     * 退出驱动
     */
    public void quit() {
        androidDriver.quit();
    }
}
